home *** CD-ROM | disk | FTP | other *** search
/ BCI NET 2 / BCI NET 2.iso / archives / programming / source / xdme_1.84_src.lha / XDME / Src / Mod / VarStack.c < prev   
Encoding:
C/C++ Source or Header  |  1994-12-03  |  11.6 KB  |  453 lines

  1. /******************************************************************************
  2.  
  3.     MODUL
  4.     $Id: VarStack.c 1.2 1994/09/20 11:05:32 b_noll Exp b_noll $
  5.  
  6.     DESCRIPTION
  7.     Variable Stack for DME/XDME
  8.  
  9.     NOTES
  10.       * we are using the non-std functions
  11.      ???    error(template, ...);
  12.      int   SetTypedVar   (const char *name, const char *value, int type);
  13.      char *GetTypedVar (const char *name, int *type);
  14.     and the argument array
  15.      UBYTE *av[];
  16.     they have to be supported by the application
  17.  
  18.     BUGS
  19.       * we are only saving the lower 8 bits of "type" from GetTypedVar!
  20.     that behaviour if not planned to be changed in the near future.
  21.     (However, if it's urgently needed, uncomment the "Type"-slot in
  22.     "VRST" and multireplace "Node.ln_Type" with "Type")
  23.  
  24.     TODO
  25.     -/-
  26.  
  27.     EXAMPLES
  28.     -/-
  29.  
  30.     SEE ALSO
  31.     vars.c
  32.  
  33.     INDEX
  34.  
  35.     HISTORY
  36.     05-12-92 b_noll created
  37.     26-08-93 VSTK_drop added
  38.     24-06-94 renamed VARS to VRST
  39.     05-09-94 added VSTK_Internal
  40.     21-09-94 b_noll added DEFCMD/DEFHELP-support
  41.     22-09-94 b_noll totally rewritten
  42.     01-10-94 b_noll introduced DEFMESSAGE
  43.  
  44. ******************************************************************************/
  45.  
  46. /***********************************************************
  47. *!
  48. *!  Variable Stacking:
  49. *!
  50. *!  Stacking for all structures, which may be read and
  51. *!  written via GetTypedVar()
  52. *!  (Please notice that stackable are only variables,
  53. *!   not macros, menues or mappings (they are stackable, but
  54. *!   popping or picking might fail))
  55. *!
  56. *!  Users should be aware to pop their entries from the stack
  57. *!  when they are needed not any more
  58. *!  (We have NOT planned to create a garbage-collector :-))
  59. *!
  60. ************************************************************/
  61.  
  62. /**************************************
  63.         Includes
  64. **************************************/
  65.  
  66. /* #include "defs.h" */
  67. #include <proto/exec.h>
  68. #include "lists.h"
  69. #include <stdio.h>
  70. #include "xdme_base.h"
  71.  
  72.  
  73. /**************************************
  74.         Globale Exports
  75. **************************************/
  76.  
  77.  
  78. /**************************************
  79.       Interne Defines & Strukturen
  80. **************************************/
  81.  
  82. /* some short names */
  83. #define MLIST struct MinList
  84. #define MNODE struct MinNode
  85. #define  NODE struct Node
  86. #define  LIST struct List
  87.  
  88.  
  89. typedef struct _VRST {
  90.     NODE    Node;
  91.     /* int     Type; */
  92.     char*   Str;
  93. } VRST;
  94. #define Type Node.ln_Type
  95.  
  96.  
  97. /* possible values for VSTK_PickPop - POP or !POP */
  98. #define POP  0
  99.  
  100. /* module internal error codes */
  101. #define VSTK_OK      0
  102. #define VSTK_NOMEM    -1
  103. #define VSTK_NOVAR    -2
  104. #define VSTK_NOENTRY    -3
  105. #define VSTK_NOTSET    -4
  106.  
  107.  
  108. /* is it sensible to put _that_ into an own function? */
  109. #define VSTK_FindEntry(n) ((VRST *)FindName((LIST *)&varstack, (n)))
  110.  
  111. /**************************************
  112.        Interne Prototypes
  113. **************************************/
  114.  
  115.  
  116. /**************************************
  117.        Impementation
  118. **************************************/
  119.  
  120. // int VSTK_Internal = 0;
  121. static MLIST varstack =
  122. { (MNODE*)&varstack.mlh_Tail, NULL, (MNODE*)&varstack.mlh_Head };
  123.  
  124. /*************************************************
  125.         Entry Level Functions
  126. *************************************************/
  127.  
  128.  
  129. /* delete an entry */
  130.  
  131. static void VSTK_FreeEntry (VRST *v) {
  132.     if (v) {
  133.     free(v->Str);
  134.     free(v->Node.ln_Name);
  135.     free(v);
  136.     } /* if */
  137. } /* VSTK_FreeEntry */
  138.  
  139.  
  140. /* remove and delete an entry */
  141.  
  142. static int VSTK_DropEntry (VRST *v) {
  143.     /* ---- Remove an entry from the stack, and free its contents and itself */
  144.  
  145.     if (v) {
  146.     Remove((NODE*)v);
  147.     VSTK_FreeEntry(v);
  148.     return VSTK_OK;
  149.     } /* if */
  150.     return VSTK_NOENTRY;
  151. } /* VSTK_DropEntry */
  152.  
  153.  
  154. /* Restore avariable from an entry and eventually delete it */
  155.  
  156. static int VSTK_PickPopEntry (VRST *v, int mode) {
  157.     /* ---- restore the value of an entry */
  158.     if (v) {
  159.     VSTK_Internal = 1;
  160.  
  161.     /* **** ATTN - we must change Vars.c for this **** */
  162.     if (!SetTypedVar(v->Node.ln_Name, v->Str, v->Type)) { /* <- EXTERNAL FUNCTION! */
  163.     /* ******************************************************* */
  164.         VSTK_Internal = 0;
  165.         return VSTK_NOTSET;
  166.     } /* if */
  167.     VSTK_Internal = 0;
  168.     if (mode == POP)
  169.         VSTK_DropEntry (v);
  170.     return VSTK_OK;
  171.     } /* if */
  172.     return VSTK_NOENTRY;
  173. } /* VSTK_PickPopEntry */
  174.  
  175.  
  176. /*************************************************
  177.         Name Level Functions
  178. *************************************************/
  179.  
  180. /* create a new entry */
  181. static
  182. int VSTK_Push (const char *name) {
  183.     VRST *v;
  184.     int type;
  185.     char *val;
  186.  
  187.     VSTK_Internal = 1;                /* ask for the variable and get the value and type */
  188.     val = GetTypedVar (name, &type);  /* <- EXTERNAL FUNCTION! */
  189.       /************************/
  190.     VSTK_Internal = 0;
  191.  
  192.     if (!val)
  193.     return (type == VAR_NEX)? VSTK_NOVAR: VSTK_NOMEM;
  194.  
  195.     if ((v = malloc (sizeof (VRST)))) {         /* allocate a node */
  196.     v->Node.ln_Name = strdup (name);        /* and space for its name */
  197.     v->Str        = val;
  198.     v->Type     = type;
  199.  
  200.     if (v->Node.ln_Name) {                  /* push the node onto the varstack */
  201.         AddHead((LIST*)&varstack, (NODE*)v);
  202.         return VSTK_OK;
  203.     } /* if */
  204.     VSTK_FreeEntry(v);
  205.     }
  206.     return VSTK_NOMEM;
  207.  
  208. } /* VSTK_Push */
  209.  
  210.  
  211. /* Restore a variable entry and eventually delete its top entry */
  212. static
  213. int VSTK_PickPop (const char *name, int mode) {
  214.     VRST *v;
  215.  
  216.     if ((v = VSTK_FindEntry(name)))
  217.     return VSTK_PickPopEntry(v, mode);
  218.     else
  219.     return VSTK_NOENTRY;
  220.  
  221. } /* VSTK_PickPop */
  222.  
  223.  
  224. /* remove the top entry of a certain name */
  225. static
  226. int VSTK_Drop (const char *name) {
  227.     VRST *v;
  228.  
  229.     if ((v = VSTK_FindEntry(name)))                 /* find the first matching node */
  230.     return VSTK_DropEntry (v);                  /* ... and drop it              */
  231.     else
  232.     return VSTK_NOENTRY;
  233.  
  234. } /* VSTK_Drop */
  235.  
  236.  
  237. /* swap the contents of a variable with that of an entry */
  238. static
  239. int VSTK_Swap (const char *name) {
  240.     VRST *v;
  241.  
  242.     if ((v = VSTK_FindEntry(name)))
  243.     {                         /* if there is a matching stack-entry */
  244.     int rv;
  245.     if ((rv = VSTK_Push(name)) != VSTK_OK)   /* push the variables current contents onto stack */
  246.         return rv;
  247.     Remove((NODE*)v);                        /* remove the elder one */
  248.     AddHead((LIST*)&varstack, (NODE*)v);     /* and set it in front of the new node */
  249.     return VSTK_PickPopEntry(v, POP);        /* and then pop it into the variable */
  250.  
  251.     } else
  252.     return VSTK_NOENTRY;
  253.  
  254. } /* VSTK_Swap */
  255.  
  256.  
  257. /* remove all entries of a certain name */
  258. static
  259. int VSTK_Purge (const char *name) {
  260.     VRST *v;
  261. #if 0
  262.     VARS *w;
  263.  
  264.     for (v = (VRST *)varstack.mlh_Head; (w = (VRST *)v->Node.ln_Succ) != NULL; v = w) /* for all nodes ... */
  265.     if (strcmp(v->Node.ln_Name, name) == 0)                                       /* if they match ... */
  266.         VSTK_DropEntry (v);                                                            /* drop them ...     */
  267. #else
  268.     /* ---- this is less code, slower but does not access the Node-slot */
  269.     while ((v = VSTK_FindEntry(name)))              /* find all matching nodes  */
  270.     VSTK_DropEntry (v);                         /* ... and drop them        */
  271. #endif
  272.  
  273.     return VSTK_OK;
  274. } /* VSTK_Purge */
  275.  
  276.  
  277. /*************************************************
  278.     Application Interface
  279. *************************************************/
  280.  
  281. /* Checks the stack for thing left from Project prj or if prj==NULL cleans the full stack. */
  282.  
  283.  
  284.  
  285. Prototype void VSTK_CloseProject (APTR prj);
  286. void VSTK_CloseProject (APTR prj) {
  287.     VRST *v;
  288.     VRST *w;
  289.  
  290. #if 1
  291.     char cmp_val[12];
  292.     sprintf (cmp_val, "%08lx", prj);
  293. #endif
  294.  
  295.     if (!prj) {
  296.     while ((v = GetHead(&varstack)))
  297.         VSTK_DropEntry (v);
  298.     return;
  299.     } /* if */
  300.  
  301.     for (v = (VRST *)varstack.mlh_Head; (w = (VRST *)v->Node.ln_Succ) != NULL; v = w) {
  302.     if (v->Type == VAR_SV) {
  303. #if 0
  304.         // ---- this is the right way, as soon as SPC_KILLSTACK is usablle
  305.         if ((l = spc_lock (v->Node.ln_Name)))
  306.         if (spc_killstack (l, v->Value, prj))
  307.             VSTK_DropEntry (v);
  308. #else
  309.         // ---- but this one is the only currently viable (and its faster)
  310.         if ((strcmp(v->Node.ln_Name, "ed") == 0) ||
  311.         (strcmp(v->Node.ln_Name, "pos") == 0) ||
  312.         (strcmp(v->Node.ln_Name, "block") == 0))
  313.         if (strncmp (v->Str, cmp_val, 8) == 0)
  314.             VSTK_DropEntry (v);
  315. #endif
  316.     } /* if */
  317.     } /* for */
  318. } /* VSTK_CloseProject */
  319.  
  320.  
  321.  
  322. /* Display a VarStack error */
  323.  
  324. static int VSTK_Error (int code) {
  325.     switch (code) {
  326.     case VSTK_OK:
  327.     return RET_SUCC;
  328.     case VSTK_NOVAR:
  329. DEFMESSAGE( _VTSK_var_not_found, "%s:\nNo Variable `%s' found!" )
  330.     error (_VTSK_var_not_found, av[0], av[1]);
  331.     break;
  332.     case VSTK_NOMEM:
  333.     nomemory();
  334. DEFMESSAGE( _VSTK_no_memory, "%s:\nNo Memory!" )
  335.     // error (_VSTK_no_memory, av[0]); // HA! HA! HA!
  336.     break;
  337.     case VSTK_NOENTRY:
  338. DEFMESSAGE( _VSTK_entry_not_found, "%s:\nNo Stackentry `%s' found!" )
  339.     error (_VSTK_entry_not_found, av[0], av[1]);
  340.     break;
  341.     case VSTK_NOTSET:
  342. DEFMESSAGE( _VSTK_set_failed, "%s:\nUnable to set Variable `%s'!" )
  343.     error(_VSTK_set_failed, av[0], av[1]);
  344.     break;
  345.     default:
  346. DEFMESSAGE( _VSTK_internal, "%s:\nInternal Error!" )
  347.     error(_VSTK_internal, av[0]);
  348.     } /* switch */
  349.  
  350.     return RET_FAIL;
  351. } /* VSTK_Error */
  352.  
  353.  
  354. /*************************************************
  355.         XDME Command Interface
  356. *************************************************/
  357.  
  358.  
  359. /*DEFHELP #cmd stack,var PUSHVAR var - push the contents of the variable @{B}var@{UB} onto the variable stack */
  360. DEFUSERCMD("PushVar", 1, CF_VWM|CF_COK|CF_ICO, int, do_pushVAR, (void),)
  361. {
  362.     return VSTK_Error(VSTK_Push(av[1]));
  363. } /* do_pushVAR */
  364.  
  365. /*DEFHELP #cmd stack,var DROPVAR var - remove the last pushed occurency of the variable @{B}var@{UB} from the variable stack */
  366. DEFUSERCMD("DropVar", 1, CF_VWM|CF_COK|CF_ICO, int, do_dropVAR, (void),)
  367. {
  368.     return VSTK_Error( VSTK_Drop(av[1]));
  369. } /* do_dropVAR */
  370.  
  371. /*DEFHELP #cmd stack,var PICKVAR var - restore the last pushed contents of the variable @{B}var@{UB} from the variable stack without modifying the variable stack */
  372. DEFUSERCMD("PickVar", 1, CF_VWM|CF_COK|CF_ICO, int, do_pickVAR, (void),)
  373. {
  374.     return VSTK_Error( VSTK_PickPop(av[1], !POP));
  375. } /* do_pickVAR */
  376.  
  377. /*DEFHELP #cmd stack,var PURGEVAR var - remove all occurencies the variable @{B}var@{UB} from the variable stack */
  378. DEFUSERCMD("PurgeVar", 1, CF_VWM|CF_COK|CF_ICO, int, do_purgeVAR, (void),)
  379. {
  380.     return VSTK_Error( VSTK_Purge(av[1]));
  381. } /* do_purgeVAR */
  382.  
  383. /*DEFHELP #cmd stack,var POPVAR var - restore the last pushed contents of the variable @{B}var@{UB} from the variable stack and remove it */
  384. DEFUSERCMD("PopVar", 1, CF_VWM|CF_COK|CF_ICO, int, do_popVAR, (void),)
  385. {
  386.     return VSTK_Error( VSTK_PickPop(av[1], POP));
  387. } /* do_popVAR */
  388.  
  389. /*DEFHELP #cmd stack,var SWAPVAR var - swap the contents of a variable with that of its last pushed entry in the variable stack */
  390. DEFUSERCMD("SwapVar", 1, CF_VWM|CF_COK|CF_ICO, int, do_swapVAR, (void),)
  391. {
  392.     return VSTK_Error( VSTK_Swap(av[1]));
  393. } /* do_swapVAR */
  394.  
  395.  
  396. #if 0 /* das wuerde nochmal ca 30 byte sparen */
  397.  
  398. int do_varstack (void) {
  399.     int rv = !POP;
  400.  
  401.     switch (av[0][2]) {
  402.     case 'a':
  403.     rv = VSTK_Swap(av[1]);
  404.     break;
  405.     case 'p':
  406. //      rv = VSTK_PickPop(av[1], POP);
  407. //      break;
  408.     rv = POP;
  409.     case 'c':
  410.     rv = VSTK_PickPop(av[1], rv);
  411.     break;
  412.     case 'o':
  413.     rv = VSTK_Drop(av[1]);
  414.     break;
  415.     case 'r':
  416.     rv = VSTK_Purge(av[1]);
  417.     break;
  418.     case 's':
  419.     rv = VSTK_Push(av[1]);
  420.     break;
  421.     default:
  422.     return RET_FAIL;
  423.     } /* switch */
  424.  
  425.     return VSTK_Error(rv);
  426. }
  427. #endif
  428.  
  429.  
  430. #ifdef SPC_VAR
  431.  
  432. generic internal bit varstackmode = %{
  433.     reference = "VSTK_Internal";
  434. %};
  435.  
  436. #endif
  437. #if 0
  438.     DEFFLAG( 94-11-15, VSTK_Internal, 0 )
  439. #endif
  440.  
  441. /******************************************************************************
  442. *****  ENDE varstack.c
  443. ******************************************************************************/
  444.  
  445.  
  446. /*DEFUSERCMD("_showstack", 0, 0, void, vstk_show, (void),)
  447. {
  448.     VRST *v;
  449.     for (v = GetHead(&varstack); v; v = GetSucc(v))
  450.     printf ("%s:%s\n", v->Node.ln_Name, v->Str);
  451. } /* vstk_show */
  452.  
  453.